package com.kinsin.kinsinlogsystem;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

// region 启动服务代码示例
//Intent intent = new Intent(this, LogcatService.class);
//LogServiceConfig logServiceConfig = new LogServiceConfig.Builder()
//		.setBasePath("/storage/emulated/legacy/example/logRollDir/") // 日志基础路径
//		.setZipPath("/storage/emulated/legacy/example/logZipPath/") // 压缩包操作路径
//		.setMaxTotalSize(530 * 1024 * 1024) // 最大容量530MB
//		.setStorageReleaseStandard(480 * 1024 * 1024) // 释放停止线 480MB
//		.setTempFileMaxSize(10 * 1024 * 1024) // 临时文件最大容量10MB
//		.setNormalWriteMode(false) // 使用映射写入
//		.setStorageCheckInterval(10) // 检测间隔10分钟
//		.setStorageCheckTimeUnit(TimeUnit.MINUTES) // 检测间隔时间单位为分钟
//		.build();
//intent.putExtra("config", logServiceConfig);
//startService(intent);
// endregion 启动服务代码示例

/**
 * 日志滚动存储服务
 * 必要：传入LogServiceConfig，建议在app中初始化配置，可以在启动服务时传入，也可以重复使用于日志发送中
 * 启动服务示例：(最上方留有方便复制的代码)
 * Intent intent = new Intent(this, LogcatService.class);
 * LogServiceConfig logServiceConfig = new LogServiceConfig.Builder()
 * 		.setBasePath("/storage/emulated/legacy/example/logRollDir/") // 日志基础路径
 * 		.setZipPath("/storage/emulated/legacy/example/logZipPath/") // 压缩包操作路径
 * 		.setMaxTotalSize(530 * 1024 * 1024) // 最大容量530MB
 * 		.setStorageReleaseStandard(480 * 1024 * 1024) // 释放停止线 480MB
 * 		.setTempFileMaxSize(10 * 1024 * 1024) // 临时文件最大容量10MB
 * 		.setNormalWriteMode(false) // 使用映射写入
 * 		.setStorageCheckInterval(10) // 检测间隔10分钟
 * 		.setStorageCheckTimeUnit(TimeUnit.MINUTES) // 检测间隔时间单位为分钟
 * 		.build();
 * intent.putExtra("config", logServiceConfig);
 * startService(intent);
 *
 *
 * 1、initFileStructure() 初始化目录结构 -- 只进行初始化，不进行文件删除
 * 2、collectLogFiles() 日志文件收集 -- 专职负责收集日志文件
 * 3、scheduleTasks() 定时任务 -- 每10分钟检查一次容量; 每日零点任务
 * 4、startLogCollector() 日志收集线程 -- 写日志，并且负责临时文件切换
 */
public class LogcatService extends Service {

    private static final String TAG = "LogcatService";

    private volatile LogServiceConfig config;
    private String logSelfPath;
    private String logSelfPathDeadRecord;

    // 执行调度器
    private ScheduledExecutorService mScheduler;
    private volatile boolean mIsRunning;
    private BufferedWriter mTmpWriter;

    private File currentFile = null;
    private final StringBuilder logCache = new StringBuilder();

    // MMap写入工具
    private KinsinMMapLogWriter mMapWriter = null;

    // 线程
    private Thread collectFileThread = null;
    private Thread collectLogThread = null;
    private Thread clearFileThread = null;

    // 普通写入与内存映射写入开关 true:普通写入  false:内存映射写入
    private final boolean IS_NORMAL_WRITE = false;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogServiceConfig innerConfig = null;
        if (intent != null) {
            innerConfig = (LogServiceConfig) intent.getSerializableExtra("config");
        }
        if (innerConfig == null) {
//            throw new IllegalStateException("Must initialize config before starting logcatService");
            Log.e(TAG, "onStartCommand: Must initialize config before starting logcatService");
            return START_NOT_STICKY;
        }
        this.config = innerConfig;
        logSelfPath = config.getBasePath() + "Log.log";

        // 初始化目录结构 -- 只进行初始化，不进行文件删除
        initFileStructure();
        // 启动日志收集线程 -- 写日志，并且负责临时文件切换
        startLogCollector();
        // 日志文件收集 -- 专职负责收集日志文件
        collectLogFiles();
        // 定时任务 -- 每10分钟检查一次容量; 每日零点任务
        scheduleTasks();
        return START_REDELIVER_INTENT; // 如果在执行完onStartCommand后，服务被异常kill掉，系统会自动重启该服务，并将Intent的值传入；
    }

    private boolean isConfigInvalid() {
        return config == null;
    }

    // 初始化目录结构
    private void initFileStructure() {
        if (isConfigInvalid()) return;
        FileUtils.createDir(config.getBasePath());
        FileUtils.createFile(logSelfPath);
    }

    /**
     * 启动日志收集线程
     */
    private void startLogCollector() {
        if (collectLogThread != null) {
            collectLogThread.interrupt();
            try {
                collectLogThread.join(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        mIsRunning = true;
        try {
            String command = "logcat -v time";
            final Process process = Runtime.getRuntime().exec(command);
            final BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream(), "UTF-8"));
            collectLogThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    String line;
                    while (mIsRunning) {
                        try {
                            // 重新初始化 logcat 进程和 reader
                            Process process = Runtime.getRuntime().exec("logcat -v time");
                            BufferedReader reader = new BufferedReader(
                                    new InputStreamReader(process.getInputStream(), "UTF-8"));

                            while ((line = reader.readLine()) != null && mIsRunning) {
                                handleLogLine(line);
                            }

                            // 如果正常退出循环，可能是流结束
                            logServicePrint("Logcat stream ended, restarting...", WARNING);

                        } catch (IOException e) {
                            logServicePrint("Log collector error: " + e.getMessage(), ERROR);
                        } finally {
                            // 关闭旧资源
                            if (reader != null) {
                                try { reader.close(); } catch (IOException ignored) {}
                            }
                            if (process != null) {
                                process.destroy();
                            }
                        }

                        // 防止频繁重启导致 CPU 过载
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            break;
                        }
                    }
                }
            });
            collectLogThread.start();

        } catch (IOException e) {
            logServicePrint("Logcat init failed: " + e.getMessage(), ERROR);
        }
    }

    /**
     * 处理日志行
     *
     * @param line
     */
    private synchronized void handleLogLine(String line) {
        try {
            // 检查当前临时文件
            checkCurrentTempFile();
            // 写入临时文件
            if (IS_NORMAL_WRITE) {
                writeToTemp(line);
            } else {
                writeToTempByMMap(line);
            }
        } catch (IOException e) {
            logServicePrint("Log write error: " + e.getMessage(), ERROR);
        }
    }

    /**
     * 检查当前临时文件，如果不存在则创建
     * 临时文件只允许此方法创建，不允许其他地方创建
     *
     * @throws IOException
     */
    private void checkCurrentTempFile() throws IOException {
        if (isConfigInvalid()) return;
        // 先检测文件是否存在，如果不存在则创建
        if (currentFile == null || !currentFile.exists()) {
            String tmpName = "tmpFile_" + getCurrentTimestamp() + ".log";
            logServicePrint("当前临时文件不存在，创建临时文件: " + tmpName, INFO);
            currentFile = new File(config.getBasePath(), tmpName);
            if (IS_NORMAL_WRITE) {
                // 检测是否有writer，如果有则关闭
                if (mTmpWriter != null) {
                    mTmpWriter.close();
                }
                // 创建新的writer
                mTmpWriter = new BufferedWriter(new OutputStreamWriter(
                        new FileOutputStream(currentFile, true), "UTF-8"));
            } else {
                // 检测是否有MMapWriter，如果有则关闭
                if (mMapWriter != null) {
                    mMapWriter.close();
                }
                // 创建新的MMapWriter
                mMapWriter = new KinsinMMapLogWriter(currentFile.getAbsolutePath(), "UTF-8");
            }
        }

        // 检查当前临时文件是否大于10MB，如果大于则进行切换
        if (currentFile != null && currentFile.length() > config.getTempFileMaxSize()) {
            // 轮转临时文件
            rotateTempFile();
            // 触发容量检查
            checkStorageCapacity();
        }
    }

    /**
     * 轮转临时文件
     * 只负责滚动，不关心文件大小，不负责创建新的临时文件，不负责移动旧的文件，不负责触发容量检查
     */
    private synchronized void rotateTempFile() {
        try {
            if (IS_NORMAL_WRITE) {
                // 关闭当前写入流
                if (mTmpWriter != null) {
                    mTmpWriter.close();
                }
                mTmpWriter = null;
            } else {
                // 关闭mMapWriter
                if (mMapWriter != null) {
                    mMapWriter.close();
                }
                mMapWriter = null;
            }
            // 重置当前文件
            currentFile = null;
        } catch (IOException e) {
            logServicePrint("File rotation failed: " + e.getMessage(), ERROR);
        }
    }

    /**
     * 使用mMap写入临时文件
     */
    private void writeToTempByMMap(String content) throws IOException {
        if (currentFile == null) {
            // 将日志写入缓存中
            logCache.append(content).append("\n");
            return;
        } else {
            if (mMapWriter == null) {
                mMapWriter = new KinsinMMapLogWriter(currentFile.getAbsolutePath(), "UTF-8");
            }
            // 将缓存中的日志写入文件
            if (logCache.length() > 0) {
                mMapWriter.writeLog(logCache.toString());
                logServicePrint("将缓存中的日志写入文件 logCache size: " + FileUtils.getHumanReadableSize(logCache.length()), INFO);
                // 清空缓存
                logCache.delete(0, logCache.length());
            }
        }
        mMapWriter.writeLog(content);
    }

    /**
     * 写入临时文件
     *
     * @param content
     * @throws IOException
     */
    private void writeToTemp(String content) throws IOException {
        if (mTmpWriter == null || currentFile == null) {
            // 将日志写入缓存中
            logCache.append(content).append("\n");
            return;
        } else {
            // 将缓存中的日志写入文件
            if (logCache.length() > 0) {
                mTmpWriter.write(logCache.toString());
                mTmpWriter.flush();
                logServicePrint("将缓存中的日志写入文件 logCache size: " + FileUtils.getHumanReadableSize(logCache.length()), INFO);
                // 清空缓存
                logCache.delete(0, logCache.length());
            }
        }
        mTmpWriter.write(content + "\n");
        mTmpWriter.flush();
    }


    // 容量检查任务
    private void scheduleTasks() {
        if (isConfigInvalid()) return;
        if (mScheduler != null) {
            mScheduler.shutdown();
        }
        mScheduler = Executors.newScheduledThreadPool(2);
        // 每10分钟容量检查
        mScheduler.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                logServicePrint("Storage check task started by scheduler", INFO);
                checkStorageCapacity();
            }
        }, config.getStorageCheckInterval(), config.getStorageCheckInterval(), config.getStorageCheckTimeUnit());

        // 每隔5秒检测一次日志处理程序是否正常
        mScheduler.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                checkLogHandleThread();
            }
        }, 5, 5, TimeUnit.SECONDS);

        // 每日零点任务
        mScheduler.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                handleDateChange();
            }
        }, getMidnightDelay(), 24 * 60 * 60 * 1000, TimeUnit.MILLISECONDS);
    }

    private void checkLogHandleThread() {
        // 检测collectLogThread是否正常运行，如果正常运行则不做动作，否则重新执行startLogCollector
        if (collectLogThread == null || !collectLogThread.isAlive()) {
            logServicePrint("Log handle thread is not alive, restarting...", WARNING);
            collectLogThread = null; // 重置线程引用
            startLogCollector();
        } else {
//            logServicePrint("Log handle thread is alive", INFO); // 不打印，太频繁
        }

    }

    /**
     * 处理日期变更事件
     */
    private void handleDateChange() {
        try {
            logServicePrint("Date change detected, handling...", INFO);
            // 强制滚动当前临时文件
            rotateTempFile();

            // 识别日志文件，打包存入对应的日志目录中，如果没有对应目录则创建
            collectLogFiles();

        } catch (Exception e) {
            logServicePrint("Date change handler error: " + e.getMessage(), ERROR);
        }
    }

    /**
     * 收集日志文件
     */
    private void collectLogFiles() {
        if (isConfigInvalid()) return;
        if (collectFileThread != null) {
            collectFileThread.interrupt();
            try {
                collectFileThread.join(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        if (collectFileThread == null) {
            collectFileThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 记录开始时间
                    long startTime = System.currentTimeMillis();
                    // 扫描根目录下的日志文件
                    File[] logFiles = new File(config.getBasePath()).listFiles(new FilenameFilter() {
                        @Override
                        public boolean accept(File dir, String name) {
                            return name.startsWith("tmpFile_") && name.endsWith(".log");
                        }
                    });
                    for (File logFile : logFiles) {
                        // 跳过当前正在写入的临时文件
                        if (currentFile != null && logFile.getAbsolutePath().equals(currentFile.getAbsolutePath())) {
                            logServicePrint("收集日志文件： 跳过正在写入的临时文件：" + logFile.getName(), INFO);
                            continue;
                        }

                        String name = logFile.getName();
                        // 文件名为固定的格式：tmpFile_yyyyMMdd_HHmmss.log，将yyyyMMdd从文件名中截取出来
                        String date = name.substring(name.indexOf("_") + 1, name.indexOf("_") + 9);
                        // 将文件拷贝到对应的日志目录中，目录格式为：backUpyyyyMMdd
                        String backupDir = "backUp" + date;
                        // 检查根目录中是否有该日志目录
                        if (!new File(config.getBasePath() + backupDir).exists()) {
                            logServicePrint("检查到不存在目录：" + config.getBasePath() + backupDir, INFO);
                            boolean dir = FileUtils.createDir(config.getBasePath() + backupDir);
                            logServicePrint("目录" + backupDir + "是否创建成功：" + dir, INFO);
                        }
                        // 将拷贝后的文件更名为固定格式：logyyyyMMdd_HHmmss.log
                        String newName = name.replaceAll("tmpFile_", "log");
                        // 执行文件移动
                        boolean isSuccess = FileUtils.move(logFile.getAbsolutePath(), config.getBasePath() + backupDir + "/" + newName);
                        if (isSuccess) {
                            logServicePrint("Collected: " + logFile.getName() + " -> " + config.getBasePath() + backupDir + "/" + newName, INFO);
                        } else {
                            logServicePrint("Failed to collect: " + logFile.getName() + ", 目标路径：" + config.getBasePath() + backupDir + "/" + newName, ERROR);
                        }
                    }
                    // 打印执行时间
                    logServicePrint("CollectLogFiles 共耗时：" + (System.currentTimeMillis() - startTime) + "ms", INFO);
                    // 重置线程变量
                    collectFileThread = null;
                }
            });
            collectFileThread.start();
        }
    }


    /**
     * 容量管理逻辑
     */
    private void checkStorageCapacity() {
        if (isConfigInvalid()) return;
        long totalSize = FileUtils.getDirectorySize(config.getBasePath());
        logServicePrint("Total size: " + FileUtils.getHumanReadableSize(totalSize), INFO);
        if (totalSize > config.getMaxTotalSize()) {
            purgeOldLogs();
        }
        maintainServiceLog();
    }

    /**
     * 清理旧日志，按时间顺序删除最旧的文件，直到总大小低于STORAGE_RELEASE_STANDARD
     */
    private void purgeOldLogs() {
        if (isConfigInvalid()) return;
        if (clearFileThread != null) {
            clearFileThread.interrupt();
            try {
                clearFileThread.join(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        if (clearFileThread == null) {
            clearFileThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 获取基础目录的总大小
                    long totalSize = FileUtils.getDirectorySize(config.getBasePath());
                    // 记录原始总大小，用于计算释放大小
                    long recordOriginalSize = totalSize;
                    // 如果总大小未超过存储释放标准，则无需清理
                    if (totalSize <= config.getStorageReleaseStandard()) {
                        clearFileThread = null;
                        return;
                    }
                    logServicePrint("检测到容量已经到达阈值" + FileUtils.getHumanReadableSize(config.getMaxTotalSize()) + "准备开始执行存储释放程序", INFO);
                    // 阶段1：删除备份目录中的旧文件
                    List<File> backupDirs = getSortedBackupDirs();
                    for (File dir : backupDirs) {
                        List<File> logFiles = getSortedLogFilesInDir(dir);
                        for (File logFile : logFiles) {
                            // 尝试删除当前日志文件并更新总大小
                            DeleteResult deleteResult = deleteFileAndUpdateSize(logFile, totalSize);
                            if (deleteResult.isDone) {
                                // 如果总大小已低于存储释放标准，则停止清理
                                logServicePrint("处于阶段一时完成空间释放：共释放出： " + FileUtils.getHumanReadableSize(recordOriginalSize - totalSize) +
                                        "， 当前占用 " + FileUtils.getHumanReadableSize(totalSize) + "/" + FileUtils.getHumanReadableSize(config.getMaxTotalSize()), INFO);
                                clearFileThread = null;
                                // 删除变空的目录
                                deleteEmptyDir(dir);
                                return;
                            } else {
                                // 更新totalSize
                                totalSize = deleteResult.newTotalSize;
                            }
                        }
                        // 删除变空的目录
                        deleteEmptyDir(dir);
                    }

                    // 阶段2：如果仍然超标，删除根目录的临时文件
                    if (totalSize > config.getStorageReleaseStandard()) {

                        List<File> tmpFiles = getSortedTempFiles();
                        for (File tmpFile : tmpFiles) {
                            // 跳过当前正在写入的临时文件
                            if (currentFile != null && tmpFile.getAbsolutePath().equals(currentFile.getAbsolutePath())) {
                                logServicePrint("清理旧日志： 跳过正在写入的临时文件：" + tmpFile.getName(), INFO);
                                continue;
                            }
                            // 尝试删除当前临时文件并更新总大小
                            DeleteResult deleteResult = deleteFileAndUpdateSize(tmpFile, totalSize);
                            if (deleteResult.isDone) {
                                // 如果总大小已低于存储释放标准，则停止清理
                                logServicePrint("处于阶段二时完成空间释放：共释放出： " + FileUtils.getHumanReadableSize(recordOriginalSize - totalSize) +
                                        "， 当前占用 " + FileUtils.getHumanReadableSize(totalSize) + "/" + FileUtils.getHumanReadableSize(config.getMaxTotalSize()), INFO);
                                clearFileThread = null;
                                return;
                            } else {
                                // 更新totalSize
                                totalSize = deleteResult.newTotalSize;
                            }
                        }
                    }

                    clearFileThread = null;
                }
            });
            clearFileThread.start();
        }

    }

    /**
     * 删除单个文件并更新总大小
     *
     * @param file      待删除的文件
     * @param totalSize 当前总大小
     * @return 如果删除后总大小低于存储释放标准，则返回true，否则返回false
     */
    private DeleteResult deleteFileAndUpdateSize(File file, long totalSize) {
        long fileSize = file.length();
        if (file.delete()) {
            logServicePrint("Deleted old file: " + file.getAbsolutePath(), INFO);
            return new DeleteResult(true, totalSize <= config.getStorageReleaseStandard(), totalSize - fileSize);
        } else {
            logServicePrint("Failed to delete: " + file.getAbsolutePath(), ERROR);
            return new DeleteResult(false, totalSize <= config.getStorageReleaseStandard(), totalSize);
        }
    }

    /**
     * 获取根目录下按时间排序的临时文件
     *
     * @return 排序后的临时文件列表
     */
    private List<File> getSortedTempFiles() {
        if (isConfigInvalid()) return new ArrayList<>();
        // 过滤并获取基础目录下所有临时文件
        File[] files = new File(config.getBasePath()).listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.startsWith("tmpFile_") && name.endsWith(".log");
            }
        });
        if (files == null) return new ArrayList<>();

        List<File> sortedFiles = new ArrayList<>(Arrays.asList(files));
        // 按时间戳对临时文件进行排序
        Collections.sort(sortedFiles, new Comparator<File>() {
            @Override
            public int compare(File f1, File f2) {
                // 从文件名提取时间戳：tmpFile_yyyyMMdd_HHmmss.log
                String time1 = f1.getName().substring(8, 21);
                String time2 = f2.getName().substring(8, 21);
                return time1.compareTo(time2);
            }
        });
        return sortedFiles;
    }


    /**
     * 删除空目录
     *
     * @param dir
     */
    private void deleteEmptyDir(File dir) {
        if (dir.exists() && dir.list().length == 0) {
            if (dir.delete()) {
                logServicePrint("Deleted empty directory: " + dir.getName(), INFO);
            } else {
                logServicePrint("Failed to delete empty directory: " + dir.getName(), ERROR);
            }
        }
    }

    /**
     * 获取按日期排序的备份目录列表（从旧到新）
     */
    private List<File> getSortedBackupDirs() {
        if (isConfigInvalid()) return new ArrayList<>();
        // 过滤并获取所有以"backUp"开头的目录
        File[] dirs = new File(config.getBasePath()).listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory() && pathname.getName().startsWith("backUp");
            }
        });
        // 如果没有找到目录，返回空列表
        if (dirs == null) {
            return new ArrayList<>();
        }
        List<File> sortedDirs = new ArrayList<>(Arrays.asList(dirs));
        // 按日期对目录进行排序
        Collections.sort(sortedDirs, new Comparator<File>() {
            @Override
            public int compare(File d1, File d2) {
                String date1 = d1.getName().substring(6); // 提取"backUp"后的日期部分
                String date2 = d2.getName().substring(6);
                return date1.compareTo(date2);
            }
        });
        return sortedDirs;
    }

    /**
     * 获取目录中按时间排序的日志文件列表（从旧到新）
     */
    private List<File> getSortedLogFilesInDir(File dir) {
        if (isConfigInvalid()) return new ArrayList<>();
        // 过滤并获取所有以"log"开头且以".log"结尾的文件
        File[] files = dir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.startsWith("log") && name.endsWith(".log");
            }
        });
        // 如果没有找到文件，返回空列表
        if (files == null) {
            return new ArrayList<>();
        }
        List<File> sortedFiles = new ArrayList<>(Arrays.asList(files));
        // 按时间戳对文件进行排序
        Collections.sort(sortedFiles, new Comparator<File>() {
            @Override
            public int compare(File f1, File f2) {
                String time1 = f1.getName().substring(3, 17); // 提取"log"后的时间戳
                String time2 = f2.getName().substring(3, 17);
                return time1.compareTo(time2);
            }
        });
        return sortedFiles;
    }


    /**
     * 维护日志本身的日志文件大小
     */
    private void maintainServiceLog() {
        if (isConfigInvalid()) return;
        File serviceLog = new File(logSelfPath);
        if (serviceLog.length() > 16 * 1024 * 1024) {
            truncateServiceLog(serviceLog);
        }
    }

    /**
     * 截断服务日志
     *
     * @param logFile
     */
    private void truncateServiceLog(File logFile) {
        try {
            String content = FileUtils.readFileToString(logFile.getAbsolutePath());
            if (content != null) {
                String[] lines = content.split("\n");
                int keepLines = lines.length / 2;
                StringBuilder sb = new StringBuilder();
                for (int i = keepLines; i < lines.length; i++) {
                    sb.append(lines[i]).append("\n");
                }
                FileUtils.writeStringToFile(sb.toString(), logFile.getAbsolutePath(), false);
            }
        } catch (Exception e) {
            logServicePrint("Log truncate error: " + e.getMessage(), ERROR);
        }
    }

    // 辅助方法
    private static String getCurrentDate() {
        return new SimpleDateFormat("yyyyMMdd").format(new Date());
    }

    private static String getCurrentTimestamp() {
        return new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    }

    private boolean isLogFile(File file) {
        String name = file.getName();
        return name.endsWith(".log") && !name.equals("Log.log");
    }

    // 午夜延迟计算
    private long getMidnightDelay() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTimeInMillis() - System.currentTimeMillis();
    }

    // 服务终止处理
    @Override
    public void onDestroy() {
        // 停止线程
        mIsRunning = false;
        if (collectLogThread != null) {
            collectLogThread.interrupt();
            try {
                collectLogThread.join(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        if (collectFileThread != null) {
            collectFileThread.interrupt();
            try {
                collectFileThread.join(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        if (clearFileThread != null) {
            clearFileThread.interrupt();
            try {
                clearFileThread.join(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        // 关闭 writer 和映射
        try {
            if (mTmpWriter != null) mTmpWriter.close();
            if (mMapWriter != null) mMapWriter.close();
        } catch (IOException e) {
            Log.e("LogcatService", "Close error", e);
        }
        if (mScheduler != null) {
            mScheduler.shutdown();
        }

        if (logSelfPath == null) {
            Log.w("LogcatService", "onDestroy: 非正常停止服务");
        } else {
            logServicePrint("日志滚动存储服务已被注销 Service stopped", WARNING);
        }
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    // 服务日志记录
    private void logServicePrint(String message, String level) {
        if (isConfigInvalid() || logSelfPath == null) return;
        try {
            if (level == null) {
                level = DEBUG;
            }
            String logEntry = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
                    + " [" + level + "] " + message + "\n";
            FileUtils.writeStringToFile(logEntry, logSelfPath, true);
        } catch (Exception e) {
            // 容错：即使写日志失败也不影响主流程
            Log.e(TAG, "Failed to write service log", e);
        }
    }

    private final static String DEBUG = "DEBUG";
    private final static String INFO = "INFO";
    private final static String WARNING = "WARNING";
    private final static String ERROR = "ERROR";

    private static class DeleteResult {
        public final boolean isDeleted;    // 是否删除成功
        public final boolean isDone; // 是否满足释放条件
        public final long newTotalSize;    // 删除后的新总大小

        public DeleteResult(boolean isDeleted, boolean isDone, long newTotalSize) {
            this.isDeleted = isDeleted;
            this.isDone = isDone;
            this.newTotalSize = newTotalSize;
        }
    }
}